package com.study.service.hystrix;

import com.netflix.hystrix.*;
import com.study.service.NacosClientService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.client.ServiceInstance;

import java.util.Collections;
import java.util.List;

import static com.netflix.hystrix.HystrixCommandProperties.ExecutionIsolationStrategy.THREAD;

/**
 * hystrix: 舱壁模式
 * 线程池
 */
@Slf4j
public class NacosClientHystrixCommand extends HystrixCommand<List<ServiceInstance>> {

    //需要保护的服务
    private final NacosClientService nacosClientService;

    //方法需要传递的参数
    private final String serviceId;

    public NacosClientHystrixCommand(NacosClientService nacosClientService,String serviceId){

        super(
                Setter.withGroupKey(
                        HystrixCommandGroupKey.Factory.asKey("NacosClientService"))
                .andCommandKey(HystrixCommandKey.Factory.asKey("NacosClientHystrixCommand"))
                .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("NacosClientPool"))
                .andCommandPropertiesDefaults(
                        HystrixCommandProperties.Setter()
                        .withExecutionIsolationStrategy(THREAD) //线程池隔离
                        .withFallbackEnabled(true)//开启降级
                        .withCircuitBreakerEnabled(true) //开启熔断
                )
        );

        this.nacosClientService = nacosClientService;
        this.serviceId = serviceId;
    }

    /**
     * 要保护的方法调用
     * @return
     * @throws Exception
     */

    @Override
    protected List<ServiceInstance> run() throws Exception {

        log.info("NacosClientService In Hystrix Command to Get Service Instance : [{}],[{}]",
                this.serviceId,Thread.currentThread().getName());

        return this.nacosClientService.getNacosClientInfo(this.serviceId);
    }

    /**
     * 降级处理策略
     * @return
     */
    @Override
    protected List<ServiceInstance> getFallback() {

        log.warn("Nacos ClientService run error: [{}],[{}] ",
                this.serviceId,Thread.currentThread().getName());

        return Collections.emptyList();
    }
}
